<?php
/**
 * @desc 登录退出控制器
 * @author yupoxiong<i@yupoxiong.com>
 */
declare (strict_types=1);

namespace app\admin\controller;

use app\admin\exception\AdminLoginLimitException;
use app\admin\exception\AdminServiceException;
use app\admin\service\LoginDeviceService;
use app\admin\validate\AdminUserValidate;
use app\admin\service\AdminAuthService;
use Webman\Captcha\CaptchaBuilder;
use support\Response;
use util\gt\GeeTest;
use support\Request;
use Exception;

class AuthController extends AdminBaseController
{

    /**
     * 登录
     * @param Request $request
     * @param AdminAuthService $service
     * @param AdminUserValidate $validate
     * @return Response
     */
    public function login(Request $request, AdminAuthService $service, AdminUserValidate $validate): Response
    {
        $redirect = $request->input('redirect', '/admin/index/index');

        $login_config = setting('admin.login');
        $captcha      = (int)$login_config['captcha'];
        $gt           = new GeeTest();

        if ($request->method() === 'POST') {
            $param = $request->all();
            try {
                // 验证码形式，0为不验证，1为图形验证码，2为极验
                if (($captcha === 1) && !captcha_check($param['captcha'])) {
                    return admin_error('验证码错误');
                }

                if ($captcha === 2) {
                    $gt_check_result = $gt->getGtSession();
                    if ($gt_check_result !== 'success') {
                        return admin_error('行为验证失败，请刷新页面重新登录');
                    }
                }

                $check = $validate->scene('login')->check($param);
                if (!$check) {
                    return admin_error($validate->getError());
                }

                // 检查单设备登录
                $service->checkLoginLimit();

                $username   = $param['username'];
                $password   = $param['password'];
                $remember   = $param['remember'] ?? 0;
                $admin_user = $service->login($username, $password);

                $device_id = $request->device_id;

                // 设置当前登录设备标识
                (new LoginDeviceService($admin_user))->setLoginDeviceId($device_id);

                $response = admin_success('登录成功', [], url($redirect));

                return $service->setAdminUserAuthInfo($admin_user, (bool)$remember, $response);


            } catch (AdminServiceException $e) {
                // 记录错误次数
                $service->setLoginLimit();
                return admin_error($e->getMessage());
            } catch (AdminLoginLimitException $e) {
                return admin_error($e->getMessage());
            }
        }

        if ($captcha === 2) {
            $gee_test_id = $login_config['gt_captcha_id'] ?? '';
            $this->assign([
                'gt_captcha_id' => $gee_test_id,
            ]);
            // 默认设置维成功
            $gt->setGtSession('success');
        }

        $this->assign([
            'redirect'     => $redirect,
            'login_config' => $login_config,
        ]);

        return $this->fetch();
    }


    /**
     * 退出
     * @param Request $request
     * @param AdminAuthService $service
     * @return Response
     */
    public function logout(Request $request, AdminAuthService $service): Response
    {
        $redirect = url($request->input('redirect') ?? 'admin/index/index');
        $response = admin_success('退出成功', [], $redirect);

        return $service->logout($request->user, $response);
    }


    /**
     * 输出验证码图像
     */
    public function captcha(Request $request): Response
    {
        // 初始化验证码类
        $builder = new CaptchaBuilder;
        // 生成验证码
        $builder->build();
        // 将验证码的值存储到session中
        $request->session()->set('captcha', strtolower($builder->getPhrase()));
        // 获得验证码图片二进制数据
        $img_content = $builder->get();
        // 输出验证码二进制数据
        return response($img_content, 200, ['Content-Type' => 'image/jpeg']);
    }


    /**
     * 极验初始化
     * @param Request $request
     * @return Response
     */
    public function gt(Request $request): Response
    {
        $gt = new GeeTest();

        $data = $gt->check($request->all());

        $status = $data['status'] ?? 'error';
        $result = $data['result'] ?? 'fail';

        if ($status === 'success' && $result !== 'success') {
            $gt->setGtSession('fail');
        } else {
            // 请求失败的时候直接设置为成功
            $gt->setGtSession('success');
        }

        return admin_success('', [
            'result' => $result,
            'status' => $status,
        ]);

    }

    /**
     * 获取token
     * @param Request $request
     * @return Response
     * @throws Exception
     */
    public function token(Request $request): Response
    {
        return $request->method() === 'POST' ? admin_success('', [
            'token' => token()
        ]) : admin_error('非法请求');
    }


}
